package cn.hdu.liang.ch6;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;


public class CyclicBarrierDemo {
    public static void main(String[] args) {
        float[][] matrix = new float[3][3];
        int counter = 0;
        for(int row = 0; row < matrix.length; row++) {
            for(int col = 0; col < matrix[0].length; col++) {
                matrix[row][col] = counter++;
            }
        }
        dump(matrix);
        System.out.println();
        Solver solver = new Solver(matrix);
        System.out.println();
        dump(matrix);
    }

    private static void dump(float[][] matrix) {
        for(float[] aMatrix : matrix) {
            for(int col = 0; col < matrix[0].length; col++) {
                System.out.print(aMatrix[col] + " ");
            }
            System.out.println();
        }
    }
}


class Solver {
    final int N;
    final float[][] data;
    final CyclicBarrier barrier;

    public Solver(float[][] matrix) {
        data = matrix;
        N = matrix.length;
        barrier = new CyclicBarrier(N, this::mergeRows);
        for(int i = 0; i < N; i++) {
            new Thread(new Worker(i)).start();
        }
        waitUntilDone();
    }

    void mergeRows() {
        System.out.println("合并");
        synchronized("abc") {
            "abc".notify();
        }
    }

    void waitUntilDone() {
        synchronized("abc") {
            try {
                System.out.println("主线程等待");
                "abc".wait();
                System.out.println("主线程提醒");
            } catch(InterruptedException ie) {
                System.out.println("主线程打断");
            }
        }
    }


    class Worker implements Runnable {
        int myRow;
        boolean done = false;

        Worker(int row) {
            myRow = row;
        }

        boolean isDone() {
            return done;
        }

        void processRow(int myRow) {
            try {
                Thread.sleep(500);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("执行行数：" + myRow);
            for(int i = 0; i < N; i++) {
                data[myRow][i] *= 10;
            }
            done = true;
        }

        @Override
        public void run() {
            while(!isDone()) {
                processRow(myRow);
                try {
                    barrier.await();
                } catch(InterruptedException | BrokenBarrierException ie) {
                    return;
                }
            }
        }
    }
}
